
#ifndef _VBIBMANAGER_H_
#define _VBIBMANAGER_H_

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
class CVBIBManager
{
private:
	static CVBIBManager mSingleInstance;

////////////////////////////////////////////////////////////////////////////////////////////////////
public:
	////////////////////////////////////////////////////////////////////////////////////////////
	enum EBufferType
	{
		eBT_Invalid = -1,
		eBT_Vertex = 0,
		eBT_Index,
		eBT_VertexDynamic,
		eBT_NumTypes
	};

	////////////////////////////////////////////////////////////////////////////////////////////
	struct SVBIBHandle
	{
		EBufferType		eType;
		DWORD			dwBufferFormat;
		DWORD			dwBufferIndex;
		DWORD			dwFirstElementOffset;	// Bytes or elements for dyn vertex buffers.
		DWORD			dwNumElements;

		SVBIBHandle() : eType(eBT_Invalid), 
						dwBufferIndex(0xFFFFFFFF),
						dwFirstElementOffset(0xFFFFFFFF),
						dwNumElements(0xFFFFFFFF)
		{
		}
	};


////////////////////////////////////////////////////////////////////////////////////////////////////
private:
	////////////////////////////////////////////////////////////////////////////////////////////
	//removed memory / size constants for hardware/software modes Imago 6/26/09
	int m_iMaxNumBuffers;
	int m_iDefaultBufferSize;
	D3DPOOL m_iDefaultBufferPool;
	D3DPOOL m_iDynamicBufferPool;

	////////////////////////////////////////////////////////////////////////////////////////////
	struct SD3DBuffer
	{
		EBufferType		eBufferType;			// Type of this buffer.
		DWORD			dwBufferFormat;			// Format of this buffer.
		DWORD			dwBufferSize;			// Bytes.
		DWORD			dwBufferOffset;			// Bytes.
		DWORD			dwElementSize;			// Size of vertex or index.

		struct									// Flags.
		{
			bool		bDefaultPool : 1;		// Resource creation pool type.
			bool		bLocked : 1;			// Currently locked.
			bool		bResourceEvicted : 1;	// Has this resource been evicted due to a device reset?
		};
		
		// Pointer to specific D3D resource.
		union 
		{
			LPDIRECT3DVERTEXBUFFER9 pVertexBuffer;
			LPDIRECT3DINDEXBUFFER9 pIndexBuffer;
		};
	};

	////////////////////////////////////////////////////////////////////////////////////////////
	struct SVBIBManagerState
	{
		// NOTE: this MUST be the FIRST item in the structure.
		bool bInitialised;

		struct
		{
			bool		bStaticVertexBufferLocked : 1;
			bool		bStaticIndexBufferLocked : 1;
		};

		DWORD dwNumBuffersAllocated;
		SD3DBuffer * pBufferArray[256]; //m_iMaxNumBuffers --imago 6/26/09 changed for < 128MB RAM
	};

	////////////////////////////////////////////////////////////////////////////////////////////
	SVBIBManagerState m_sVBIB;

////////////////////////////////////////////////////////////////////////////////////////////////////
public:
	////////////////////////////////////////////////////////////////////////////////////////////
	CVBIBManager();
	virtual ~ CVBIBManager();

	////////////////////////////////////////////////////////////////////////////////////////////
	static inline CVBIBManager * Get() { return &mSingleInstance;	}

	////////////////////////////////////////////////////////////////////////////////////////////
	void Initialise( );

	////////////////////////////////////////////////////////////////////////////////////////////
	void Shutdown( );

	////////////////////////////////////////////////////////////////////////////////////////////
	void EvictDefaultPoolResources( );

	////////////////////////////////////////////////////////////////////////////////////////////
	bool AllocateVertexRegion(	SVBIBHandle * pResult,
										DWORD dwNumVertices,
										DWORD dwVertexSize,
										DWORD dwFVF,
										void ** ppData );

	////////////////////////////////////////////////////////////////////////////////////////////
	bool AllocateIndexRegion(	SVBIBHandle * pResult,
										DWORD dwNumIndices,
										D3DFORMAT d3dIndexFormat,
										void ** ppData );

	////////////////////////////////////////////////////////////////////////////////////////////
	bool ReleaseRegion( SVBIBHandle * pHandle );

	////////////////////////////////////////////////////////////////////////////////////////////
	bool AddVerticesToBuffer(	SVBIBHandle * pResult,
										BYTE * pVertices,
										DWORD dwNumVertices,
										DWORD dwVertexSize,
										DWORD dwFVF );

	////////////////////////////////////////////////////////////////////////////////////////////
	bool AddIndicesToBuffer(		SVBIBHandle * pResult,
										BYTE * pIndices,
										DWORD dwNumIndices,
										D3DFORMAT d3dIndexFormat );

	////////////////////////////////////////////////////////////////////////////////////////////
	bool AddLegacyVerticesToBuffer(	SVBIBHandle * pResult,
											BYTE * pVertices,
											DWORD dwNumVertices,
											DWORD dwVertexSize,
											DWORD dwFVF );

	////////////////////////////////////////////////////////////////////////////////////////////
	bool AddLegacyLitVerticesToBuffer(	SVBIBHandle * pResult,
												BYTE * pVertices,
												DWORD dwNumVertices,
												DWORD dwVertexSize,
												DWORD dwFVF );

	////////////////////////////////////////////////////////////////////////////////////////////
	bool AllocateDynamicVertexBuffer(	SVBIBHandle * pResult,
												DWORD dwMaxVertices,
												DWORD dwVertexSize,
												DWORD dwFVF );

	////////////////////////////////////////////////////////////////////////////////////////////
	bool LockDynamicVertexBuffer(	SVBIBHandle * pHandle,
											DWORD dwNumVertsRequired,
											void ** ppbData );

	////////////////////////////////////////////////////////////////////////////////////////////
	bool UnlockDynamicVertexBuffer(	SVBIBHandle * pHandle );

	////////////////////////////////////////////////////////////////////////////////////////////
	HRESULT SetVertexAndIndexStreams( const SVBIBHandle * pVB, const SVBIBHandle * pIB );

	////////////////////////////////////////////////////////////////////////////////////////////
	HRESULT SetVertexStream( const SVBIBHandle * pVB );

	////////////////////////////////////////////////////////////////////////////////////////////
	HRESULT SetIndexStream( const SVBIBHandle * pIB );

////////////////////////////////////////////////////////////////////////////////////////////////////
private:
	DWORD FindBuffer(	EBufferType eBufferType, 
								DWORD dwFormat, 
								DWORD dwElementSize,
								DWORD dwNumElements );
};

#endif // _VBIBMANAGER_H_